package cn.iocoder.yudao.module.trade.service.order.handler;

import cn.iocoder.yudao.framework.common.enums.trade.TradeOrderStatusEnum;
import cn.iocoder.yudao.framework.common.enums.trade.TransactionTypeEnum;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.yudao.module.member.api.config.dto.MemberConfMaterialDTO;
import cn.iocoder.yudao.module.member.api.config.dto.MemberConfRespDTO;
import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO;
import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO;
import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum;
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderOrderCreateReqVO;
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderOrderReqVO;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Objects;

import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_CREATE_FAIL_USER_NO_PERMISSION;

/**
 * 锁价卖料交易模式处理器
 */
@Component
public class PriceLockSellTransactionHandler extends AbstractTransactionModeHandler {

    private static final TransactionTypeEnum TRANSACTION_TYPE = TransactionTypeEnum.PRICE_LOCK_SELL;

    @Override
    public Integer getTransactionType() {
        return TRANSACTION_TYPE.getType();
    }

    @Override
    public void validatePermission(MemberConfRespDTO memberConf) {
        if (Boolean.FALSE.equals(memberConf.getFullPayBuy())) {
            throw ServiceExceptionUtil.exception(ORDER_CREATE_FAIL_USER_NO_PERMISSION, TRANSACTION_TYPE.getDesc());
        }
    }
    
    @Override
    public void validateTradeLimits(MemberConfMaterialDTO materialConf, AppTradeOrderOrderReqVO settlementReqVO) {
        // 调用父类的通用限制校验
        super.validateTradeLimits(materialConf, settlementReqVO);
        
//        // 锁价卖料特有限制校验
//        if (materialConf.getPriceLockMinSellPrice() != null &&
//            settlementReqVO.getPrice().compareTo(materialConf.getPriceLockMinSellPrice()) < 0) {
//            throw ServiceExceptionUtil.exception(ORDER_CREATE_FAIL_BELOW_PRICE_LOCK_MIN_SELL_PRICE);
//        }
//
//        // 锁价卖料期限检查
//        if (materialConf.getLockPeriod() != null &&
//            (settlementReqVO.getLockPeriod() == null || settlementReqVO.getLockPeriod() > materialConf.getLockPeriod())) {
//            throw ServiceExceptionUtil.exception(ORDER_CREATE_FAIL_LOCK_PERIOD_EXCEED);
//        }
    }

    @Override
    protected void setPriceResult(TradePriceCalculateReqBO calculateReqBO, TradePriceCalculateRespBO result, TradePriceCalculateRespBO context) {
        if (context.getDeposit().compareTo(BigDecimal.ZERO) > 0) {
            result.setPayType(PayNotifyTypeEnum.ORDER_DEPOSIT.getType());
        } else {
            result.setPayType(PayNotifyTypeEnum.ORDER.getType());
        }

    }

    @Override
    protected BigDecimal calculatePayPrice(TradePriceCalculateReqBO calculateReqBO, TradePriceCalculateRespBO calContext) {
        BigDecimal livePrice = livePriceApi.getConfPrice(calculateReqBO.getMetalType(), false);
        BigDecimal deposit = super.calculateDeposit(calculateReqBO.getWeight(), calculateReqBO.getMetalConf().getDepositWeight(),
                calculateReqBO.getLivePrice(), livePrice, BigDecimal.ZERO);
        calContext.setDeposit(deposit);
        return deposit;
    }


    /**
     * 总额、定金、延期费、工费、附加费
     */
    @Override
    public PayOrderCreateReqDTO creatSettlePay(TradeOrderDO order, Boolean isViolate) {
        PayOrderCreateReqDTO payOrder = super.initPayOrderCreate(order.getOrderNo());
        // 已支付单
        PayOrderRespDTO payOrderRespDTO = payOrderApi.getOrder(order.getPayOrderId());
        // 现价
        BigDecimal livePriceReclaim = livePriceApi.getConfPrice(order.getMetalType(), false);

        /*
            违约结算:
            不用在支付任何费用(需要保证结算时定金率>=20% )
            正常结算:
            应支付= 净金价 + (延期费-已交延期费) + (工费-已交工费) + (附加费 - 已交附加费) - 已交定金
        */

        // 1.需补定金 = 基础定金 + (当前价格-下单价格) * weight / 定金参数 * 10 - 已交定金 （一般是定金不足的情况下需要计算）
        BigDecimal depositFee = super.calculateDeposit(order.getWeight(), order.getDepositPriceConf(),
                order.getOrderPrice(), livePriceReclaim, payOrderRespDTO.getDeposit());
        // 2. 净金价
        BigDecimal metalPrice = order.getMetalPrice();

        // 3.延期费 = （当前日期 - 下单日期 - 免息天数 ） * 延期费配置  - 已交延期费
        BigDecimal delayFee = super.calculateDelayPrice(order.getCreateTime(), order.getInterestFreeDays(),
                payOrderRespDTO.getDelayPrice(), order.getDelayFeeConf(), order.getWeight());

        // 4.工费 = （克重 * 工费配置） - 已交工费
        BigDecimal processFee = super.calculateProducePrice(order.getWeight(), order.getProcessConf(), payOrderRespDTO.getProcessPrice());

        // 5.附加费 = 附加费 - 已交附加费
        BigDecimal deductPrice = order.getDeductPrice();
        //  检验结果单、需要成色 按售价
        BigDecimal additionalFee;
        BigDecimal addWeight = order.getWeight().subtract(order.getConvertWeight());
        int a = addWeight.compareTo(BigDecimal.ZERO);
        if (a == 0) {
            additionalFee = BigDecimal.ZERO;
        } else if (a > 0){
            BigDecimal livePriceSell = livePriceApi.getConfPrice(order.getMetalType(), true);
            // 少的补钱
            additionalFee = addWeight.multiply(livePriceSell);
        } else {
            // 多的回收
            additionalFee = addWeight.multiply(livePriceReclaim);
        }
        additionalFee = additionalFee.subtract(payOrderRespDTO.getAdditionalPrice()).setScale(2, RoundingMode.HALF_UP).add(deductPrice);

        // 服务费
        BigDecimal price = depositFee.add(delayFee).add(processFee).add(additionalFee);

        // 违约结算
        if (isViolate) {
            payOrder.setIsViolate(true);
            payOrder.setPayType(PayNotifyTypeEnum.SETTLE_BOOM.getType());
            // 多的定金退回?
            if (price.compareTo(BigDecimal.ZERO) < 0) {
                payOrder.setPrice(BigDecimal.ZERO);
            } else {
                payOrder.setDelayPrice(delayFee);
                payOrder.setProcessPrice(processFee);
                payOrder.setDeposit(depositFee);
                payOrder.setAdditionalPrice(additionalFee);
                payOrder.setPrice(price);
            }
            return payOrder;
        }
        // 正常结算
//        payOrder.setDeposit(BigDecimal.ZERO.subtract(payOrderRespDTO.getDeposit()));
        payOrder.setDelayPrice(delayFee);
        payOrder.setProcessPrice(processFee);
//        payOrder.setAdditionalPrice();
        payOrder.setPrice(metalPrice.add(delayFee).add(processFee).add(additionalFee)
//                .subtract(payOrderRespDTO.getDeposit())
        );
        return payOrder;
    }
    @Override
    public void setupDeliveryInfo(TradeOrderDO order, Long userId, AppTradeOrderOrderCreateReqVO createReqVO) {
        order.setDeliveryType(createReqVO.getDeliveryType());
        // 快递配送
        createStoreAddr(order, createReqVO.getPickUpStoreId(), order.getOrderNo(), DeliveryTypeEnum.EXPRESS_TO_SHOP, createReqVO.getPickupInfoId());

    }

    /*
     * 锁价模式:多次付款
     *
     */
    @Override
    public TradeOrderStatusEnum getNextStatusBySuceess(TradeOrderDO order, Integer payType, Boolean isStore) {
        TradeOrderStatusEnum nowStatus = TradeOrderStatusEnum.getEnum(order.getStatus());
        // TODO: 2025/3/27 无实物结算，生成结算单按照直接买卖
        if (PayNotifyTypeEnum.isSettle(payType)) {
            if (PayNotifyTypeEnum.SETTLE_BOOM.getType().equals(payType)) {
                return TradeOrderStatusEnum.CLOSED;
            }
        }
        switch (nowStatus) {
            case UNPAID -> {
                if (PayNotifyTypeEnum.ORDER_DEPOSIT.getType().equals(payType)) {
                    if (DeliveryTypeEnum.PICK_UP.getType().equals(order.getDeliveryType())) {
                        return TradeOrderStatusEnum.UNPICK_MEMBER;
                    }
                    return TradeOrderStatusEnum.UNDELIVERED_MEMBER;
                }
                return TradeOrderStatusEnum.UNPAID;
            }

            case UNDELIVERED_MEMBER -> {
                return TradeOrderStatusEnum.WAIT_CHECK;
            }
            case WAIT_CHECK -> {
                return TradeOrderStatusEnum.CHECK_DONE;
            }
            // 待上门 --(验金)--> 验金完成 --(创建结算单)--> 待确认 --(支付成功)--> 已结算
            case CHECK_DONE -> {
                return TradeOrderStatusEnum.WAIT_CONFIRM;
            }
            case WAIT_CONFIRM, SETTLING, WAIT_PAY_CHECK-> {
                if (DeliveryTypeEnum.PICK_UP.getType().equals(order.getDeliveryType())) {
                    return TradeOrderStatusEnum.COMPLETED;
                }
                return TradeOrderStatusEnum.PREPARE;
            }
            case PREPARE -> {
                return TradeOrderStatusEnum.DELIVERED;
            }
            case DELIVERED -> {
                return TradeOrderStatusEnum.COMPLETED;
            }
        }
        return null;
    }
} 